package com.bosssoft.trainee.gateway.filter;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.bosssoft.trainee.gateway.util.ResponseUtil;
import com.bosssoft.trainee.mbg.result.CommonResult;
import com.bosssoft.trainee.security.config.IgnoreUrlsConfig;
import com.bosssoft.trainee.security.util.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @Author: wuxin
 * @Date: 2022/6/17
 * @Project rbac
 * @Version 1.0
 * @Description
 */
@Slf4j
public class MyTokenFilter implements GlobalFilter{
    @Autowired
    ReactiveUserDetailsService reactiveUserDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;


    /**
     * Process the Web request and (optionally) delegate to the next {@code WebFilter}
     * through the given {@link GatewayFilterChain}.
     *
     * @param exchange the current server exchange
     * @param chain    provides a way to delegate to the next filter
     * @return {@code Mono<Void>} to indicate when request processing is complete
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        if (ignoreUrlsConfig.getUrls().contains(exchange.getRequest().getPath().value())){
            return chain.filter(exchange);
        }
        log.info("该请求需要token校验");
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        ServerHttpResponse response = exchange.getResponse();
        // token不存在
        if (tokenHeader==null||StringUtils.isEmpty(tokenHeader)) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
            return ResponseUtil.out(response,CommonResult.forbidden("尚未登录"));
        }
        // 取token
        String token = tokenHeader.substring(this.tokenHead.length());
        log.info("token=" + token);

        // token不存在
        if (StringUtils.isEmpty(token)) {
            log.info("token不存在");
            response.setStatusCode(HttpStatus.FORBIDDEN);
            return ResponseUtil.out(response,CommonResult.forbidden("尚未登录"));
        }

        String username = jwtTokenUtil.getUserNameFromToken(token);
        log.info("checking username:{}", username);
        // 校验 token是否正确
        if (username == null) {
            log.info("token对应的username不存在");
            response.setStatusCode(HttpStatus.FORBIDDEN);
            return ResponseUtil.out(response,CommonResult.forbidden("尚未登录"));
        }
        return chain.filter(exchange);
    }
}
